home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
comm2
/
xbtx.lha
/
Source
/
IOSerial.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-03
|
13KB
|
713 lines
/*
** $Id: IOSerial.cpp 1.6 1995/12/03 12:16:23 olsen Exp olsen $
**
** :ts=4
*/
/*
* Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
*
* Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
* Erlangen-Nuremberg, Germany.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* Erlangen-Nuremberg, Germany.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software has not been validated by the ``Bundesamt fuer Zulassungen in
* der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
* must not be used for accessing the BTX-Network of the Telekom in Germany.
*
* Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
* der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
* am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
*/
/****************************************************************************/
#include <string.h>
#include <stdio.h>
/****************************************************************************/
#ifndef _IOSERIAL_HPP
#include "IOSerial.hpp"
#endif
#ifndef _CONTROL_H
#include "Control.h"
#endif
#ifndef _RAWKEYS_H
#include "RawKeys.h"
#endif
/****************************************************************************/
#define D(x)
/******************** This is CONTROL SET C0 of CEPT ***********************/
#define NOBLOCK 0 /* not receiving a block */
#define TEXTBLOCK 1 /* normal text block */
#define IMAGEBLOCK 2 /* transparent block */
#define ERROR 0 /* status error */
#define NUL 0x00 /* Null (data link) */
#define SOH 0x01 /* start of heading (data link) */
#define STX 0x02 /* start text (data link) */
#define ETX 0x03 /* end text (data link) */
#define EOT 0x04 /* end of transmission (data link) */
#define ENQ 0x05 /* enquiry (data link) */
#define ACK 0x06 /* acknowledge (data link) */
#define ITB 0x07 /* end intermediate block (data link) */
#define APB 0x08 /* active position back (control sequence) */
#define APF 0x09 /* active position forward (control sequence) */
#define APD 0x0a /* active position down (control sequence) */
#define APU 0x0b /* active position up (control sequence) */
#define CS 0x0c /* clear screen (control sequence) */
#define APR 0x0d /* active position return (control sequence) */
#define LS1 0x0e /* locking shift 1 (control sequence) */
#define LS0 0x0f /* locking shift 0 (control sequence) */
#define DLE 0x10 /* data link escape (data link) */
#define CON 0x11 /* cursor on (control sequence) */
#define RPT 0x12 /* repeat last character (control sequence) */
#define INI 0x13 /* initiator '*' (btx special) */
#define COF 0x14 /* cursor off (control sequence) */
#define NAK 0x15 /* negative acknowledge (data link) */
#define SYN 0x16 /* (data link) */
#define ETB 0x17 /* end textblock (data link) */
#define CAN 0x18 /* cancel,clear eol (control sequence) */
#define SS2 0x19 /* single shift for G2 SET (control sequence) */
#define DCT 0x1a /* (btx special) */
#define ESC 0x1b /* escape (control sequence) */
#define TER 0x1c /* terminator '#' (btx special) */
#define SS3 0x1d /* single shift for G3 SET (control sequence) */
#define APH 0x1e /* active position home (control sequence) */
#define US 0x1f /* active position (x,y) (control sequence) */
/****************************************************************************/
// For crc 16 bit calculation using run-time generated table
#define calccrc(c) crc=(UWORD)(crctab[((crc) ^ (c)) & 0xff] ^ ((crc) >> 8))
/****************************************************************************/
VOID IOSerial::Close(VOID)
{
if(Raw)
{
delete Raw;
Raw = NULL;
}
}
LONG IOSerial::Open(CONST STRPTR Channel,ULONG Unit,ULONG Baud,BOOL RTS_CTS)
{
LONG Error;
Close();
if(Raw = new IORawSerial)
{
if(Error = Raw->Open(Channel,Unit,Baud,RTS_CTS))
{
delete Raw;
Raw = NULL;
}
}
else
Error = -1;
return(Error);
}
VOID IOSerial::PutString(CONST STRPTR String,LONG Len)
{
if(Raw)
{
UBYTE *From;
UBYTE *s,*t;
char *str;
UBYTE c;
if(Len < 0)
Len = strlen(String);
s = (UBYTE *)String;
t = s + Len;
From = s;
str = NULL;
c = 0;
while(s < t)
{
switch(*s)
{
case 'Ä':
str = "\310A";
break;
case 'ä':
str = "\310a";
break;
case 'Ö':
str = "\310O";
break;
case 'ö':
str = "\310o";
case 'Ü':
str = "\0310U";
break;
case 'ü':
str = "\310U";
break;
case KEY_CursorUp:
c = APU;
break;
case KEY_CursorDown:
c = APD;
break;
case '\b':
case 127:
case KEY_CursorLeft:
c = APB;
break;
case KEY_CursorRight:
c = APF;
break;
case KEY_Help:
c = APH;
break;
case '*':
c = INI;
break;
case '#':
case '\r':
case '\n':
c = TER;
break;
}
if(str || c)
{
if(From < s)
Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
From = s + 1;
if(str)
{
Raw->PutString((CONST STRPTR)str,strlen(str));
str = NULL;
}
else
{
Raw->PutChar(c);
c = 0;
}
}
s++;
}
if(From < s)
Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
}
}
/* modeminput: this is data link layer (level 2) for getting blocks from
* btx, crc check is done and characters are send to client
*/
int IOSerial::modeminput(LONG Timeout)
{
LONG c1;
UBYTE c;
BOOL eaten;
if(buffered > 0 && buffer_input)
{
if(buffered-- == 1)
buffer_input = FALSE;
return((int)buffer[bufferindex++]);
}
for(;;)
{
c1 = getmodem(Timeout);
if(c1 < 0)
return(c1);
else
c = (UBYTE)c1;
switch( block )
{
case IMAGEBLOCK:
eaten = FALSE;
switch(c)
{
case DLE:
if(got_dle)
got_dle = FALSE;
else
{
got_dle = TRUE;
eaten = TRUE;
}
break;
case ENQ:
if(got_dle)
{
buffered = bufferlen = 0;
buffer_input = FALSE;
ack01 = '0';
block = NOBLOCK;
got_itb_bcc = FALSE;
putmodem(DLE);
putmodem(ack01);
eaten = TRUE;
got_dle = FALSE;
}
break;
case EOT:
if(status == ERROR || got_dle)
{
buffered = bufferlen = 0;
buffer_input = FALSE;
ack01 = '0';
block = NOBLOCK;
got_itb_bcc = FALSE;
eaten = TRUE;
got_dle = FALSE;
}
break;
case ITB:
case ETB:
case ETX:
if(got_dle)
{
got_dle = FALSE;
calccrc(c);
eaten = TRUE;
if(getcheck(Timeout) || status == ERROR)
{
buffered = bufferlen = 0;
buffer_input = FALSE;
crc = 0;
putmodem(NAK);
status = ERROR;
got_itb_bcc = FALSE;
got_dle = FALSE;
break;
}
status = c;
block = NOBLOCK;
if(c == ITB)
{
putmodem(ACK);
got_itb_bcc = TRUE;
}
else
{
ack01 ^= 1;
putmodem(DLE);
putmodem(ack01);
got_itb_bcc = FALSE;
}
if(bufferlen > 0)
{
buffer_input = TRUE;
buffered = bufferlen - 1;
bufferindex = 1;
bufferlen = 0;
return((int)buffer[0]);
}
}
break;
}
if(!eaten)
{
calccrc(c);
if(bufferlen < BLOCK_BUFFER_SIZE-1)
{
buffer[bufferlen++] = c;
got_itb_bcc = FALSE;
}
else
D(printf("Blockbuffer overflow !\n"));
}
break;
case TEXTBLOCK:
calccrc(c);
switch(c)
{
case DLE:
case NAK:
case ACK:
case SOH:
D(printf("Bad char:%x\n",c1));
got_itb_bcc = FALSE;
break;
case STX:
if(status == ERROR || status == ETB)
{
crc = 0;
bufferlen = 0;
status = EOT;
got_itb_bcc = FALSE;
}
break;
case EOT:
ack01 = '0';
block = NOBLOCK;
got_itb_bcc = FALSE;
break;
case ITB:
case ETB:
case ETX:
if(getcheck(Timeout) || status == ERROR)
{
buffer_input = FALSE;
buffered = bufferlen = 0;
crc = 0;
putmodem(NAK);
status = ERROR;
got_itb_bcc = FALSE;
break;
}
status = c;
if(c == ITB)
{
putmodem(ACK);
got_itb_bcc = TRUE;
}
else
{
ack01 ^= 1;
putmodem(DLE);
putmodem(ack01);
if(c == ETX)
block = NOBLOCK; /* end of textblock */
got_itb_bcc = FALSE;
}
if(bufferlen > 0)
{
buffer_input = TRUE;
buffered = bufferlen - 1;
bufferindex = 1;
bufferlen = 0;
return((int)buffer[0]);
}
break;
case ENQ:
switch( status )
{
case ERROR:
case EOT:
putmodem(NAK);
break;
case ITB:
putmodem(ACK);
putmodem(NAK);
break;
case ETX:
case ETB:
putmodem(DLE);
putmodem(ack01);
putmodem(NAK);
break;
}
got_itb_bcc = FALSE;
break;
default:
if(bufferlen < BLOCK_BUFFER_SIZE-1)
{
buffer[bufferlen++] = c;
got_itb_bcc = FALSE;
}
else
D(printf("Blockbuffer overflow !\n"));
break;
}
break;
default: /* NOBLOCK */
status = EOT;
if(tfi)
{
if(tfi == SOH)
tfi = ENQ;
else
{
if(c == ENQ)
{
D(printf("send TFI\n"));
send_TFI();
}
tfi = 0;
}
}
switch(c)
{
case DLE:
got_dle = TRUE;
break;
case ENQ:
if(got_dle)
{
putmodem(DLE);
putmodem('0');
}
got_dle = FALSE;
break;
case EOT:
ack01 = '0';
got_dle = FALSE;
break;
case SOH:
tfi = SOH;
crc = 0;
block = TEXTBLOCK;
bufferlen = 0;
got_dle = FALSE;
break;
case STX:
if(got_dle)
block = IMAGEBLOCK;
else
block = TEXTBLOCK;
crc = 0;
bufferlen = 0;
if(got_dle && got_itb_bcc)
{
got_itb_bcc = FALSE;
calccrc(DLE);
calccrc(STX);
}
got_dle = FALSE;
break;
default:
got_dle = FALSE;
return((int)c);
}
break;
}
}
}
void IOSerial::send_TFI()
{
putmodem(SOH);
putmodem('@'); /* @ = intermediate blocksize */
putmodem('5'); /* 5 = max. 256 bytes */
putmodem(ETX);
}
/* get 2 bytes from modem and calccrc, return value is crc (should be 0 if
* no crc error), during check handle socket inputs
*/
UWORD IOSerial::getcheck(LONG Timeout)
{
LONG c;
int i;
for(i = 0 ; i < 2 ; )
{
c = getmodem(Timeout);
if(c >= 0)
{
calccrc((unsigned int)c);
i++;
}
}
if(crc)
D(printf("CRC error %x\n",(int)crc));
return(crc);
}
/******************************************************************************/
IOSerial::IOSerial()
{
UWORD crc;
int i,j;
Raw = NULL;
block = NOBLOCK;
bufferlen = 0;
tfi = 0;
ack01 = '0';
status = EOT;
crc = 0;
buffered = 0;
buffer_input = FALSE;
got_dle = FALSE;
got_itb_bcc = FALSE;
for(i = 0 ; i < 256 ; i++)
{
crc = (UWORD)i;
for(j = 0 ; j < 8 ; j++)
{
if(crc & 1)
crc = (UWORD)((crc >> 1) ^ 0xa001);
else
crc >>= 1;
}
crctab[i] = crc;
}
}
IOSerial::~IOSerial()
{
Close();
}